package main

import (
	"time"
	"fmt"
	"strconv"
)

const (
	Cpp = 1 << iota // Cpp 的值为 1 (2^0)
	Onep            // Onep 的值为 2 (2^1)
	Ninep           // Ninep 的值为 4 (2^2)
	Tenp            // Tenp 的值为 8 (2^3)
	Scg             // Scg 的值为 16 (2^4)
	Rp              // Rp 的值为 32 (2^5)
	Onepp           // Onepp 的值为 64 (2^6)
	Ccg             // Ccg 的值为 128 (2^7)
	Twop            // Twop 的值为 256 (2^8)
	Twopp           // Twopp 的值为 512 (2^9)
	Fourp           // Fourp 的值为 1024 (2^10)
)

const (
	Pulse = iota // Pulse 的值为 0
	Add          // Add 的值为 1
	Cont         // Cont 的值为 2
)

//clocks 切片包含多个整数对，每个对代表一个时钟周期或脉冲组合
var clocks = []int{
	0, Tenp, // 0: 第一个元素为0，第二个元素为Tenp (8)。可能表示某种初始化或空状态。
	Onep | Ninep, Tenp, // 1: 第一个元素为Onep (2) 和 Ninep (4) 的组合 (6)，第二个元素为Tenp (8)。
	Twop | Ninep, Tenp, // 2: 第一个元素为Twop (256) 和 Ninep (4) 的组合 (260)，第二个元素为Tenp (8)。
	Twop | Ninep, Tenp, // 3: 同上。
	Twopp | Ninep, Tenp, // 4: 第一个元素为Twopp (512) 和 Ninep (4) 的组合 (516)，第二个元素为Tenp (8)。
	Twopp | Ninep, Tenp, // 5: 同上。
	Fourp | Ninep, Tenp, // 6: 第一个元素为Fourp (1024) 和 Ninep (4) 的组合 (1028)，第二个元素为Tenp (8)。
	Fourp | Ninep, Tenp, // 7: 同上。
	Fourp | Ninep, Tenp, // 8: 同上。
	Fourp | Ninep, Tenp, // 9: 同上。
	Onepp, 0, // 10: 第一个元素为Onepp (64)，第二个元素为0。可能表示某种特殊状态。
	Ccg, 0, // 11: 第一个元素为Ccg (128)，第二个元素为0。
	0, 0, // 12: 两个元素均为0。可能表示空闲或等待状态。
	Rp, 0, // 13: 第一个元素为Rp (32)，第二个元素为0。
	0, 0, // 14: 两个元素均为0。
	0, 0, // 15: 两个元素均为0。
	0, 0, // 16: 两个元素均为0。
	Cpp, 0, // 17: 第一个元素为Cpp (1)，第二个元素为0。
	0, 0, // 18: 两个元素均为0。
	Rp, 0, // 19: 第一个元素为Rp (32)，第二个元素为0。
}

var cmode = Cont
var cyc = 0
var intbch chan int
var cyperiod = 0

// 返回当前周期的状态
func cycstat() string {
	if cyc >= len(clocks) {
		// 如果当前周期超出 clocks 数组的长度，则返回 "0"
		return "0"
	} else {
		// 否则返回当前周期的字符串表示
		return fmt.Sprintf("%d", cyc)
	}
}

// 重置周期状态机
func cycreset() {
	oldmode := cmode // 保存当前模式
	cmode = Cont     // 将模式设置为连续模式 (Cont)
	cyperiod = 0     // 重置周期时间

	// 如果 intbch 通道不为空且之前的模式是 Add 或 Pulse，则发送信号到 intbch 通道
	if intbch != nil && (oldmode == Add || oldmode == Pulse) {
		intbch <- 1
	}
}

// 控制周期操作的函数
func cyclectl(cch chan [2]string) {
	for {
		x := <-cch // 从控制通道接收命令
		switch x[0] {
		case "op":
			// 处理操作命令
			oldmode := cmode // 保存当前模式
			switch x[1] {
			case "1p", "1P":
				// 设置模式为脉冲模式 (Pulse)
				cmode = Pulse
			case "1a", "1A":
				// 设置模式为加法模式 (Add)
				cmode = Add
			case "co", "CO":
				// 设置模式为连续模式 (Cont)
				cmode = Cont
				// 如果之前的模式是 Add 或 Pulse，则发送信号到 intbch 通道
				if oldmode == Add || oldmode == Pulse {
					intbch <- 1
				}
			case "cy", "CY":
				// 循环切换模式
				cmode = (cmode + 1) % 3
				// 如果之前的模式是 Add 或 Pulse，则发送信号到 intbch 通道
				if oldmode == Add || oldmode == Pulse {
					intbch <- 1
				}
			default:
				// 输出错误信息，提示有效的操作命令
				fmt.Println("cycle unit op swtch value: one of 1p, 1a, co, cy")
			}
		case "rate":
			// 处理速率命令
			cyrate, _ := strconv.Atoi(x[1]) // 将字符串转换为整数
			if cyrate == 0 {
				// 如果速率为0，设置周期时间为0
				cyperiod = 0
			} else {
				// 否则计算周期时间（单位：微秒）
				cyperiod = 500000 / cyrate
			}
		default:
			// 输出错误信息，提示有效的控制命令
			fmt.Println("cycle unit switch: s cy.op.val")
		}
	}
}

// 周期单元主循环函数
func cycleunit(cch chan pulse, bch chan int) {
	var p pulse // 定义一个脉冲变量

	// 初始化内部通道 intbch
	intbch = make(chan int)

	// 启动一个 goroutine 来处理 bch 通道的消息
	go func() {
		for {
			b := <-bch // 从 bch 通道接收消息
			if cmode == Add || cmode == Pulse {
				// 如果当前模式是 Add 或 Pulse，则将消息转发到 intbch 通道
				intbch <- b
			}
		}
	}()

	p.resp = make(chan int) // 初始化脉冲响应通道

	for {
		if cmode == Add {
			// 如果当前模式是 Add，则等待 intbch 通道的消息
			<-intbch
		}

		// 遍历所有的时钟周期
		for cyc = 0; cyc < len(clocks); cyc++ {
			if cmode == Pulse {
				// 如果当前模式是 Pulse，则等待 intbch 通道的消息
				<-intbch
			}

			// 特殊处理第32个周期
			if cyc == 32 && (initclrff[0] || initclrff[1] || initclrff[2] ||
				initclrff[3] || initclrff[4] || initclrff[5]) {
				p.val = Scg // 设置脉冲值为 Scg
				cch <- p    // 发送脉冲到 cch 通道
				<-p.resp    // 等待响应
			} else if clocks[cyc] != 0 {
				// 如果当前周期的值不为0，则设置脉冲值并发送
				p.val = clocks[cyc]
				cch <- p
				if cyperiod != 0 {
					// 如果周期时间不为0，则休眠一段时间
					time.Sleep(time.Duration(cyperiod) * time.Microsecond)
				}
				<-p.resp // 等待响应
			} else if cyperiod != 0 {
				// 如果周期时间不为0且当前周期的值为0，则仅休眠
				time.Sleep(time.Duration(cyperiod) * time.Microsecond)
			}

			cyc++
			if clocks[cyc] != 0 {
				// 如果下一个周期的值不为0，则设置脉冲值并发送
				p.val = clocks[cyc]
				cch <- p
				if cyperiod != 0 {
					// 如果周期时间不为0，则休眠一段时间
					time.Sleep(time.Duration(cyperiod) * time.Microsecond)
				}
				<-p.resp // 等待响应
			} else if cyperiod != 0 {
				// 如果周期时间不为0且下一个周期的值为0，则仅休眠
				time.Sleep(time.Duration(cyperiod) * time.Microsecond)
			}
		}
	}
}
